\section{Отрицательные индексы массивов}
\label{negative_array_indices}

Возможно адресовать место в памяти \IT{перед} массивом задавая отрицательный индекс, например, $array[-1]$.

\subsection{Адресация строки с конца}

\myindex{Python}
\ac{PL} Питон позволяет адресовать строки с конца.
Например, \IT{string[-1]} возвращает последний символ, \IT{string[-2]} возвращает предпоследний, итд.
Трудно поверить, но в \CCpp это также возможно:

\lstinputlisting[style=customc]{\CURPATH/pythonesque_addressing.c}

Это работает, но \textit{s\_end} должен всегда содержать адрес оконечивающего нулевого байта строки \textit{s}.
Если длина строки \textit{s} изменилась, \textit{s\_end} должен обновится.

Это сомнительный трюк, но опять же, это хорошая демонстрация отрицательных индексов.

\subsection{Адресация некоторого блока с конца}

Вначале вспомним, почему стек растет в обратную сторону (\myref{stack_grow_backwards}).
Есть в памяти какой-то блок и вам нужно держать там и кучу (heap) и стек, и вы не уверены, насколько вырастут обе
структуры во время исполнения кода.

Вы можете установить указатель \IT{heap} в начало блока,
затем установить указатель \IT{stack} в конец блока (\IT{heap + size\_of\_block}),
затем вы можете адресовать \IT{n-ый} элемент стека как \IT{stack[-n]}.
Например, \IT{stack[-1]} для 1-го элемента, \IT{stack[-2]} для 2-го, итд.

Это работает точно так же, как и трюк с адресацией строки с конца.

Проверять, не пересекаются ли структуры друг с другом легко:
просто убедится что адрес последнего элемента в \IT{heap} всегда меньше чем адрес последнего элемента в \IT{stack}.

К сожалению, индекс $-0$ работать не будет,
т.к. способ представления отрицательных чисел (\IT{дополнительный код}, \myref{sec:signednumbers})
не поддерживает отрицательный ноль,
так что он не будет отличим от положительного ноля.

Этот метод также упоминается в ``Transaction processing'' Jim Gray, 1993,
глава ``The Tuple-Oriented File System'', стр. 755.

\subsection{Массивы начинающиеся с 1}
\label{arrays_at_one}

\myindex{Фортран}
\myindex{Mathematica}
В Фортране и Mathematica первый элемент массива адресуется как 1-ый, вероятно, потому что так традиционно в математике.
Другие \ac{PL} как \CCpp адресуют его как 0-й.
Как лучше?
\myindex{Эдсгер Дейкстра}
Эдсгер Дейкстра считал что последний способ лучше
\footnote{See \url{https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html}}.

Но привычка у программистов после Фортрана может остаться, так что все еще возможно адресовать
первый элемент через 1 в \CCpp используя этот трюк:

\lstinputlisting[style=customc]{\CURPATH/neg_array.c}

\lstinputlisting[caption=\NonOptimizing MSVC 2010,label=neg_array_c,numbers=left,style=customasmx86]{\CURPATH/neg_array_RU.asm}

Так что у нас тут массив \TT{array[]} из десяти элементов, заполненный байтами $0 \ldots 9$.

Затем у нас указатель \TT{fakearray[]} указывающий на один байт перед \TT{array[]}.
\TT{fakearray[1]} указывает точно на \TT{array[0]}.
Но нам все еще любопытно, что же находится перед \TT{array[]}?
Мы добавляем \TT{random\_value} перед \TT{array[]} и установим её в \TT{0x11223344}.
Неоптимизирующий компилятор выделяет переменные в том же порядке, в котором они 
объявлены, так что да, 32-битная \TT{random\_value} находится точно перед массивом.

Запускаем, и:

\begin{lstlisting}
first element 0
second element 1
last element 9
array[-1]=11, array[-2]=22, array[-3]=33, array[-4]=44
\end{lstlisting}

Фрагмент стека, который мы скопипастим из окна стека в \olly (включая комментарии автора):

\lstinputlisting[caption=\NonOptimizing MSVC 2010]{\CURPATH/stack_RU.txt}

Указатель на \TT{fakearray[]} (\TT{0x001DFBD3}) это действительно адрес \TT{array[]} в стеке (\TT{0x001DFBD4}), 
но минус 1 байт.

Трюк этот все-таки слишком хакерский и сомнительный. Вряд ли кто-то будет его использовать в своем коде,
но для демонстрации, он здесь очень уместен.

